#include "pch.h"
#include "CppUnitTest.h"
#include "../ForTest.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace Base
{
	TEST_CLASS(TestUniqueFactorization)
	{
	public:
		TEST_METHOD(TestMethod11)
		{
			CUniqueFactorization uf1({ 2,3 }, { 1,2 }), uf2({ 2,4 }, { 3,4 });
			auto uf3 = uf1 + uf2;
			AssertEx(make_pair(2, 4), uf3.m_data[0]);
			AssertEx(make_pair(3, 2), uf3.m_data[1]);
			AssertEx(make_pair(4, 4), uf3.m_data[2]);
		}
		TEST_METHOD(TestMethod12)
		{
			CUniqueFactorization uf1({ 2,3 }, { 1,2 }), uf2({ 2,4 }, { 3,4 });
			auto uf3 = uf2 + uf1;
			AssertEx(make_pair(2, 4), uf3.m_data[0]);
			AssertEx(make_pair(3, 2), uf3.m_data[1]);
			AssertEx(make_pair(4, 4), uf3.m_data[2]);
		}
		TEST_METHOD(TestMethod13)
		{
			CUniqueFactorization uf1({ 2,3,5 }, { 1,2,3 }), uf2;
			uf2 = uf1.negation();
			AssertEx(make_pair(2, -1), uf2.m_data[0]);
			AssertEx(make_pair(3, -2), uf2.m_data[1]);
			AssertEx(make_pair(5, -3), uf2.m_data[2]);
		}
		TEST_METHOD(TestMethod14)
		{
			CUniqueFactorization uf1({ 2,3,5 }, { -1,2,-3 }), uf2;
			uf2 = uf1.negation();
			AssertEx(make_pair(2, 1), uf2.m_data[0]);
			AssertEx(make_pair(3, -2), uf2.m_data[1]);
			AssertEx(make_pair(5, 3), uf2.m_data[2]);
		}
		TEST_METHOD(TestMethod15)
		{
			CUniqueFactorization uf1(2, 1), uf2(2, -1);
			auto uf3 = uf2 + uf1;
			AssertEx(0u, uf3.m_data.size());
			auto uf4 = uf2.Add(uf1);
			AssertEx(make_pair(2, 0), uf4.m_data[0]);
		}
		TEST_METHOD(TestMethod16)
		{
			CUniqueFactorization uf1(2, 1), uf2(2, -2);
			auto uf3 = uf2 + uf1;
			AssertEx(make_pair(2, -1), uf3.m_data[0]);
		}
		TEST_METHOD(TestMethod17)
		{
			CUniqueFactorizationFactory uff(19260817);
			auto uf = uff.Factorization(19260817);
			AssertEx(make_pair(19260817, 1), uf.m_data[0]);
			//AssertEx(0, uf.Cnt(1));
			//AssertEx(1, uf.Cnt(2));
			//AssertEx(0, uf.Cnt(3));
			//AssertEx(2, uf.Cnt(4));
			//AssertEx(0, uf.Cnt(5));
		}
		TEST_METHOD(TestMethod18)
		{
			CUniqueFactorization uf(2, 3);
			AssertEx(8, uf.Union().first);
			AssertEx(1, uf.Union().second);
		}
		TEST_METHOD(TestMethod19)
		{
			CUniqueFactorization uf({ 2,3 }, { 1,-1 });
			AssertEx(2, uf.Union().first);
			AssertEx(3, uf.Union().second);
		}
		TEST_METHOD(TestMethod20)
		{
			CUniqueFactorization<long long> uf(2, 32);
			AssertEx(1LL << 32, uf.Union().first);
			AssertEx(1LL, uf.Union().second);
		}
		TEST_METHOD(TestMethod21)
		{
			auto ll = 1'000'000'0019ll;
			CUniqueFactorizationFactory<long long> uff(ll);
			auto uf = uff.Factorization(ll);
			AssertEx(make_pair(ll, 1), uf.m_data[0]);
		}
		TEST_METHOD(TestMethod22)
		{
			auto ll = 10007LL;
			CUniqueFactorizationFactory<long long> uff(ll);
			auto uf = uff.Factorization(ll);
			AssertEx(make_pair(ll, 1), uf.m_data[0]);

		/*	auto ll = 1'000'000'0019ll;
			CUniqueFactorizationFactory<long long> uff(ll);
			for (int i = 10000;; i++)
			{
				auto uf = uff.Factorization(i);
				bool b = (uf.m_data.size() > 1) || (uf.m_data[0].second != 1);
				wstring str = wstring(L"i=")+to_wstring(i);
				Assert::IsTrue(b, str.c_str());
			}*/
		}
	};

	TEST_CLASS(Testaxby1)
	{
	public:
		TEST_METHOD(TestMethod11)
		{
			Test(-100);
		}
		TEST_METHOD(TestMethod12)
		{
			Test(1'000'000);			
		}
		TEST_METHOD(TestMethod13)
		{
			Test(1'000'000'000);
		}
		void Test(int begin) {
			for (int i = begin; i <= begin + 200; i++)
			{
				for (int j = i; j <= begin + 200; j++) {
					const auto g = gcd(i, j);
					Caxby1 ab(i, j);
					auto [x1, y1] = ab.Any();
					int res = i * x1 + j * y1;
					AssertEx(ab.G, res);
				}
			}
		}
	};
}
